回溯法和栈的思想用于“八皇后问题”的求解

八皇后问题是一个经典的问题,其核心是:在n*n的棋盘上,有n个皇后,这些皇后必须位于不同行不同列上,并且不能处于同一对角线上,否则会因相互攻击而死亡。那么如何安排皇后们的位置呢?

我们可以利用回溯法,先确定第一个皇后的位置,之后进入下一行,确定第二个皇后的位置,再之后进入下一行,如果发现找不到一个位置安排新皇后,则回退到上一行,将上一行的皇后向后移动一列,再考虑下一行的皇后,如此循环,直到安排好所有的皇后为止。附上一张图片以便于理解。
这里写图片描述

具体实现的代码及所遇到的问题及解决如下:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int status;

/*打印答案*/
status printsolution(int *x,int n){
    int i=1,j=1;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            /*如果该列可以放皇后,打印“Q”*/ 
            if(j==x[i])
               printf("Q");
            else
               printf("*");//不能则打印星号 
        }
        printf("\n");
    }
    printf("\n");
}

status isplace(int *x,int k){
    int i=1;//从第一行开始考察
    /*考察前k-1行*/
    for(i=1;i<=k-1;i++){
        /*这是皇后相互攻击的条件*/ 
        if((x[i]==x[k])||(fabs(x[i]-x[k])==fabs(i-k)))
           return FALSE; 
    } 
    return OK;
}

status nqueen(int *x,int n){
    int k=1;
    x[k]=0;//先让x[k]=0,进入循环后加1 
    while(k>0){//全部行列判断完后,k=0 
        x[k]++;
        while(x[k]<=n&&!isplace(x,k))//寻找可以放的列 
            x[k]++;
        if(x[k]<=n){//如果找到 
            if(k==n)//k==n说明是完整解 
                printsolution(x,n);
            else{//k<n是不完整解 
                k++;//移动到下一行继续判断 
                x[k]=0;//移动到下一行之后要注意将x[k]置为0,以便从第一行开始判断 
            }
        }
        else//x[k]如果大于n,则不必考虑此行,k--回溯到上一行 
            k--;
    }
}

int main(void){
    int * x;
    int num=0;
    x=(int *)malloc(sizeof(int)*(num+1));//这里用动态数组存储可以放置皇后的列 
    printf("请输入皇后数目");
    scanf("%d",&num); 
    nqueen(x,num);
}

2016/4/15更新:
今天复习了八皇后问题,在此过程中发现了不少之前忽视的问题,下面加以总结以便回顾反思。
问题主要出现在status nqueen()函数中

status nqueen(int *x,int n){
    int i=1;
    x[i]=0;
    while(i>0){
        x[i]++;
        while(x[i]<=n&&!isplace(x,i))
             x[i]++;
        if(x[i]<=n){//此处进行判断的条件是x[i]<=n,因为前一步在寻找能够放皇后的列 
            if(i==n)//这一步的判断条件为i==n,因为x[i]==n不能说明找到了完整解,这两处很容易出错,今后应谨慎对待 
                printsolution(x,n);
            else{
                i++;
                x[i]=0;//这一步在移动到下一行时一定要让列置为0 
            }
        }
        else
            i--;
    }
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
皇后问题是一个经典的回溯问题,以下是求解问题的代码: ```python class EightQueens: def __init__(self, n): self.n = n # 棋盘大小 self.solution = [-1] * n # 解数组 def is_valid(self, row, col): # 判断当前位置是否合 for i in range(row): # 判断同一列是否有皇后 if self.solution[i] == col: return False # 判断对角线是否有皇后 if abs(i - row) == abs(self.solution[i] - col): return False return True def backtrack(self, row): # 找到解 if row == self.n: print(self.solution) return # 遍历每一列 for col in range(self.n): # 判断当前位置是否合 if self.is_valid(row, col): self.solution[row] = col # 继续寻找下一行的解 self.backtrack(row + 1) # 回溯 self.solution[row] = -1 def solve(self): self.backtrack(0) if __name__ == '__main__': n = 8 eight_queens = EightQueens(n) eight_queens.solve() ``` 在这个代码中,我们定义了一个 EightQueens 类,其中包含了 is_valid 和 backtrack 两个函数。is_valid 函数用来判断当前位置是否合,backtrack 函数用来回溯求解皇后问题。 在主函数中,我们创建了一个 EightQueens 对象,然后调用了 solve 函数来求解皇后问题求解过程中,我们遍历每一行,对于每一行,我们遍历每一列,判断当前位置是否合,如果合,就将皇后放置在该位置,然后继续寻找下一行的解。如果找到了解,就输出解。如果没有找到解,就回溯到上一行,重新寻找解

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值